SPI(Serial Peripheral Interface)是主從式同步串列通訊,可分為單工/半雙工/全雙工。
主要應用在EEPROM、快閃記憶體、AD轉換、部分LCD上都會使用,SPI屬於高速、全雙工且具同步的通訊網路,連結外部設備時只需要四條線就可以完成通訊,同時節省了空間。
SPI可以分為Master與Slave兩種模式,但需注意的是一個SPI通訊系統中只可以有一個Master設備,所以的操作都會由Master主動發起,若連接多個設備時則可以透過CS來選擇要通訊的Slave。
優點: 僅需4條線有效減少空間、全雙工通訊、資料傳送快
缺點: 沒有ACK機制,在資料可靠度較差,需要由使用者自行確定資料正確
STM32中的SPI:
SPI Pin腳
具有4條線(3線也行但僅限單向傳輸EX:主設備傳送至從設備),四條線分別為MISO、MOSI、SCLK、CS
MISO (Master In Slave Out) | 主設備接收 從設備傳送 |
---|---|
MOSI (Master Out Slave In) | 主設備傳送 從設備接收 |
SCLK | 系統時鐘訊號 (由主設備產生) |
CS | 選擇從設備 (由主設備控制),一般預設為低電位選中。 |
下方是一對一接法,分別將兩設備對應的Pin腳對接即可,箭頭為傳輸方向。 | |
下方是一對多接法,分別將兩設備的MISO、MOSI、SCLK相連後,利用不同腳位連接Slave之CS腳位,箭頭為傳輸方向。當需要選擇任一Slave時將對應CS腳位拉低即可選擇。 |
SPI通訊有4種不同的模式,可以查找設備的DataSheet看看支援那些模式~
模式 | CPOL | CPHA |
---|---|---|
Mode 0 | 0 | 0 |
Mode 1 | 0 | 1 |
Mode 2 | 1 | 0 |
Mode 3 | 1 | 1 |
CPOL : 用來設定SCLK的電位,什麼時候是忙碌什麼時候是空閒
CPHA : 決定資料採樣點是在第幾個邊緣
//hspi SPI編號
//pData 要發送的資料
//Size 資料大小 (byte)
//TimeOut 逾時
HAL_StatusTypeDef HAL_SPI_Transmit(SPI_HandleTypeDef *hspi, uint8_t *pData, uint16_t Size, uint32_t Timeout)
//hspi SPI編號
//pData 資料接收buf
//Size 資料大小 (byte)
//TimeOut 逾時
HAL_StatusTypeDef HAL_SPI_Receive(SPI_HandleTypeDef *hspi, uint8_t *pData, uint16_t Size, uint32_t Timeout)
(SPI工作方式是每發送1個bit就會同步接收一個bit),在使用是要注意所設的緩衝器大小
//hspi SPI編號
//pTxData
//pRxData 資料接收buf
//Size 資料大小 (byte)
//TimeOut 逾時
HAL_StatusTypeDef HAL_SPI_TransmitReceive(SPI_HandleTypeDef *hspi, uint8_t *pTxData, uint8_t *pRxData, uint16_t Size,uint32_t Timeout)
同樣的與前面所提到USART一樣,除了輪詢方式以外同樣有中斷的傳送方式~
//hspi SPI編號
//pData 要發送的資料
//Size 資料大小 (byte)
//TimeOut 逾時
HAL_StatusTypeDef HAL_SPI_Transmit_IT(SPI_HandleTypeDef *hspi, uint8_t *pData, uint16_t Size)
//hspi SPI編號
//pData 資料接收buf
//Size 資料大小 (byte)
//TimeOut 逾時
HAL_StatusTypeDef HAL_SPI_Receive_IT(SPI_HandleTypeDef *hspi, uint8_t *pData, uint16_t Size)
//hspi SPI編號
//pTxData
//pRxData 資料接收buf
//Size 資料大小 (byte)
//TimeOut 逾時
HAL_StatusTypeDef HAL_SPI_TransmitReceive_IT(SPI_HandleTypeDef *hspi, uint8_t *pTxData, uint8_t *pRxData, uint16_t Size)
__weak void HAL_SPI_RxCpltCallback(SPI_HandleTypeDef *hspi)
{
/* Prevent unused argument(s) compilation warning */
UNUSED(hspi);
/* NOTE : This function should not be modified, when the callback is needed,
the HAL_SPI_RxCpltCallback should be implemented in the user file
*/
}
__weak void HAL_SPI_TxRxCpltCallback(SPI_HandleTypeDef *hspi)
{
/* Prevent unused argument(s) compilation warning */
UNUSED(hspi);
/* NOTE : This function should not be modified, when the callback is needed,
the HAL_SPI_TxRxCpltCallback should be implemented in the user file
*/
}